package mac10.roles;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;

import de.dailab.jiactng.agentcore.ontology.IAgentDescription;

import mac10.connection.MessageConstants;
import mac10.models.Cell;
import mac10.models.Point;
import mac10.models.WorldModel;
import mac10.util.AStarHeapSwitcher;
import mac10.util.Node;

public class Switcher extends AbstractRole {

	public Switcher(IAgentDescription thisAgent, WorldModel worldModel) {
		super(thisAgent, worldModel, true, true, true, true);
	}

	public String executeTask(WorldModel worldModel, String task, int posx,
			int posy, long deadline, boolean custom) {
		this.worldModel = worldModel;
		String pos[] = task.split(",");
		int tmpX = Integer.parseInt(pos[0]);
		int tmpY = Integer.parseInt(pos[1]);

		//abmelden von fences
		final Cell positon = this.worldModel.getCell(posx, posy);
		if(positon.isFence())
		{
			MasterSwitcher.staticMasterSwitcher.deregister(this.thisAgent, positon);
		}
				
		
		String msg = " " + this.thisAgent.getName()+ " Mein Ziel " + tmpX + "," + tmpY + " Bin an "+ posx + "," + posy;
		// testen ob ich schon den switch öffne
		ArrayList<Cell> switchNeighbours = worldModel.getSwitchOpeningCells(tmpX, tmpY);
		for (Cell cell : switchNeighbours)
		{

			if (cell.getX() == posx && cell.getY() == posy) 
			{
//				System.out.println("Bin da "+ msg);
				return MessageConstants.ACTION_SKIP;
			}
		}

		//für jede cell einen pfad suchen, wenn einer gefunden wurde dahin gehen
        Cell[] neighbours = switchNeighbours.toArray(
                new Cell[switchNeighbours.size()]);
        
        Arrays.sort(neighbours, new Comparator<Cell>()
        {
            public int compare (Cell a, Cell b)
            {
                double distA = WorldModel.getDistanceDouble(a, positon);
                double distB = WorldModel.getDistanceDouble(b, positon);
                if (distA == distB)
                    return 0;
                else if (distA > distB)
                    return 1;
                else
                    return -1;
            }
        });

        
        ArrayList<Point> pointsToAvoid = worldModel.getFencesForSwitch(new Point(tmpX, tmpY));


        
        for (Cell cell : neighbours) {
			LinkedList<String> actions = this.findPath(worldModel, posx, posy,
					cell.getX(), cell.getY(), deadline+200, true, true, false, false, pointsToAvoid);
			
			if(actions != null)
			{
				return actions.getFirst();
			}

		}
        MasterSwitcher.staticMasterSwitcher.deregisterSwitcher(thisAgent);
		System.out.println("Switcher konnte kein Weg finden " + msg);
		return null;
	}
	
	/**
     * Meldet Fences an.
     * @param worldModel
     * @param startx
     * @param starty
     * @param goalx
     * @param goaly
     * @param deadline
     * @param avoidAgents
     * @param avoidCows
     * @param avoidFences
     * @return
     */
    // TODO parameterListe überarbeiten auf Cell oder point umstellen
    public LinkedList<String> findPath(WorldModel worldModel, int startx,
            int starty, int goalx, int goaly, long deadline,
            boolean avoidAgents, boolean avoidCows, boolean avoidOpenFences, boolean avoidClosedFences,
            ArrayList<Point> pointsToAvoid)
    {
        
        worldModel = WorldModel.staticWorldModel;
        Point start = new Point(startx, starty);
        Point goal = new Point(goalx, goaly);
        if (start.equals(goal))
        {
            LinkedList<String> skip = new LinkedList<String>();
            skip.add(MessageConstants.ACTION_SKIP);
            return skip;
        }
        if (goal.equals(this.lastTarget)) 
        {
            if (checkPath(this.actions, startx, starty, 2))
            {
                return this.actions;
            }
        }
        //Neues Ziel deshalb von allen switchen abmelden
        

        MasterSwitcher.staticMasterSwitcher.deregister(thisAgent);
        this.lastTarget = goal;
        

        
        
        AStarHeapSwitcher astar = new AStarHeapSwitcher(worldModel, start, goal, pointsToAvoid);
        astar.setAvoidAgents(avoidAgents);
        astar.setAvoidCows(avoidCows);
        astar.setAvoidOpenFences(avoidOpenFences);
        astar.setAvoidClosedFences(avoidClosedFences);
//      long time = System.currentTimeMillis();
        Node to = astar.AStar(deadline);
        // Node to = AStarHeapStatic.AStar(this.worldModel,start, goal);
//      System.err.println("Time needed for A*: " +
//              (System.currentTimeMillis()-time));
        LinkedList<String> actions = null;
         
        if(to != null)
        {
            actions = Switcher.nodeToActionStrings(to);
        }
        else
        {
            return null;
        }
            

        
        // Anmeldung des ersten fence auf dem Weg
        Cell fence = getFirstFenceCellOnPath(to);
        if (fence != null)
        {
            MasterSwitcher.staticMasterSwitcher.register(thisAgent, fence);
        }
        
//        String action = actions.getFirst();
//        if(action != null)
//        {
//              System.err.println(thisAgent.getName() + " switcher normal move from ("+startx+", "+starty+") to "+action);
//        }
//        else
//            System.err.println(thisAgent.getName() + " action null");
        
        return actions;
    }
	

	public String toString() {
		return "switcher";
	}
	

	
}

